package com.ymatou.iapi.optrade.testcase;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.http.client.ClientProtocolException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFeeTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFreightTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.LogisticsTypeEnum;
import com.ymatou.iapi.optrade.parameter.req.AgreeRefundReq;
import com.ymatou.iapi.optrade.parameter.req.ApplyRefundReq;
import com.ymatou.iapi.optrade.parameter.utill.Utils;
import com.ymatou.iapi.optrade.parameter.vo.SalesRefundInfoVo;
import com.ymatou.iapi.optrade.resp.Order;
import com.ymatou.iapi.optrade.resp.TradingServiceResp;
import com.ymatou.iapi.optrade.service.AgreeRefundCall;
import com.ymatou.iapi.optrade.service.PrepaidCardService;
import com.ymatou.iapi.optrade.service.RefundService;
import com.ymatou.iapi.synctrade.service.TradingSyncService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.tag.P1;
import com.ymt.utils.tag.P3;
import com.ymttest.business.service.AccountCallServiceV2;
import com.ymttest.business.service.PayGateWayCallService;
import com.ymttest.business.service.YMTTrading.TradingCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceAnliOrderCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceAuthenticateCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceEngageOrderCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceOrderCallService;
import com.ymttest.business.service.YMTTrading.TradingProductVo;
import com.ymttest.database.model.AccountEntry;
import com.ymttest.database.sharding.db.sharding.model.OrderDetailPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sharding.model.RefundBillPo;
import com.ymttest.database.sharding.db.sharding.model.RefundFundPo;
import com.ymttest.database.sharding.db.sharding.model.UserRefundFundDetailPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.utils.DataUtil;

public class Ts_AgreeRefund {

	private static AgreeRefundReq salesrefundsuccessReq;
	private static AgreeRefundCall salesrefundsuccessCall;
	private static OrderShardingWapper orderShardingWapper = new OrderShardingWapper();
	
	private static long userId = 20238699;

	@BeforeClass
	public static void setUp() {

		Logger.createResultFile("退货/退款成功完成接口");
	}

	@Before
	public void caseUp() {

		salesrefundsuccessReq = new AgreeRefundReq();
		salesrefundsuccessCall = new AgreeRefundCall();
	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(salesrefundsuccessCall.getOpurl());
//		orderShardingWapper.activeDeadCommunicationsLink(orderShardingWapper);
	}

	@After
	public void caseDown() {
		Logger.end();
		orderShardingWapper.activeDeadCommunicationsLink(orderShardingWapper);
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_001() {
		Logger.start(true, "余额全款支付。确认收货前,订单多个商品依次全部全款退款");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			Long userId = placeOrderResp.getUserId();
			Long orderId = order.getOrderId();

			// 支付
			TradingCallService.payOrder(placeOrderResp.getUserId(),
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			List<OrderDetailPo> orderDetailPoList = order
					.getOrderDetailPoList();
			
			Thread.sleep(15000);
			
			Map<String, Integer> beforeStockNums = new HashMap<String, Integer>();

			for (OrderDetailPo orderDetailPo : orderDetailPoList) {

				String proId = orderDetailPo.getProductId();
				String calId = orderDetailPo.getCatalogId();

				int stockNum = TradingProductVo.getStockNum(proId, calId,
						false);

				beforeStockNums.put(calId, stockNum);

				Logger.comment(String.format(
						"proId：%s,calalogId:%s 下单之后的库存:%s", proId, calId,
						stockNum));
			}

			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					DataUtil.verifyDecimalEquals(
							RefundService.getAccountEntry(userId,
									orderId + "_" + refundBillNo + "_" + 1,
									refundBillNo).getAmount(),
							refund.getRefundAmount(), "校验取消订单退款余额入账流水金额");
				}

				Thread.sleep(30000);

				for (OrderDetailPo orderDetailPo : orderDetailPoList) {

					String proId = orderDetailPo.getProductId();
					String calId = orderDetailPo.getCatalogId();

					int stockNum = TradingProductVo.getStockNum(proId, calId,
							false);

					Logger.comment(String.format(
							"proId：%s,calalogId:%s 退单之后的库存:%s", proId, calId,
							stockNum));

					Logger.verifyEquals(beforeStockNums.get(calId)
							+ orderDetailPo.getProductCount(), stockNum,
							"校验退款完成会后商品库存返还");
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_002() {
		Logger.start(true, "全部第三方支付宝支付。确认收货前,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), BigDecimal.ZERO,
					placeOrderResp.getTradingId(), "13");

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall("13",
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_003() {
		Logger.start(true, "余额+第三方支付宝组合支付。确认收货前,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = new BigDecimal(270);

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_004() {
		Logger.start(true, "全部第三方微信支付。确认收货前,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String payTypeString = "15";
			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), BigDecimal.ZERO,
					placeOrderResp.getTradingId(), payTypeString);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payTypeString,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(3000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall(payTypeString,
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	@Ignore
	public void Tc_AgreeRefund_007() {
		Logger.start(true, "组合支付,订单部分退款,然后确认收货");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = new BigDecimal(70);

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(20000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			// 发货
			TradingCallService.delivery(order.getSellerId(), orderId, false);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);

			applyRefundReq.getSalesRefundInfoList().remove(1);
			applyRefundReq.getSalesRefundInfoList().remove(1);

			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			salesrefundsuccessReq.setRefundBillNo(applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo());
			salesrefundsuccessCall.setData(salesrefundsuccessReq);

			Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId,
					i + 1));

			salesrefundsuccessCall.callService();

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(5000);

				TradingCallService.confirmReceive(userId, orderId);

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < 1; j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_008() {
		Logger.start(true, "组合支付,接单后,一个订单多个商品，货全部退完,订单状态为用户取消，剩余部分金额给商家结算");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = new BigDecimal(70);

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(15000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);

			// 货退完，款还有部分未退
			applyRefundReq.getSalesRefundInfoList().forEach(
					re -> re.setRefundAmount(re.getRefundAmount().subtract(
							BigDecimal.TEN)));

			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(4000);

			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), userId.intValue());

			Thread.sleep(3000);

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper.selectOrderbyOrderId(orderId);

			Logger.verifyEquals(12, orderPo.getOrderStatus(), "校验订单状态为用户取消12");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	// TODO 后续校验退款生成的结算单
	public void Tc_AgreeRefund_009() {
		Logger.start(true, "余额+第三方支付宝组合支付。确认收货后,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long sellerId = order.getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ONE;

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(6000);

			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			// 发货
			TradingCallService.delivery(sellerId, orderId, false);
			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall(paytype,
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(3000);

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);

				BigDecimal tempCouponAmount = BigDecimal.ZERO;
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);

					BigDecimal deductedCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						deductedCouponAmount = order.getOrderPo()
								.getYmtCouponAmount()
								.subtract(tempCouponAmount);
					}

					else {
						deductedCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount(), Utils
												.zeroIfNull(order.getOrderPo()
														.getYmtCouponAmount()));

						tempCouponAmount = tempCouponAmount
								.add(deductedCouponAmount);
					}

					expectedRefundBillPo
							.setDeductedCouponAmount(deductedCouponAmount);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 商家扣款流水记录
					AccountEntry sellerAccountEntry = RefundService
							.getAccountEntry(sellerId, orderId + "_"
									+ refundBillNo + "_" + 1, refundBillNo);

					DataUtil.verifyDecimalEquals(
							refund.getRefundAmount()
									.add(expectedRefundBillPo
											.getDeductedCouponAmount())
									.divide(new BigDecimal(-1)),
							sellerAccountEntry.getAmount(),
							String.format(
									"退款单号 refundBillNo : %s 校验商家 sellerId : %s 账户退款 扣款 流水记录 ",
									refundBillNo, sellerId));
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_010() {
		Logger.start(true, "全部第三方支付宝支付。确认收货后,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long sellerId = order.getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			// 发货
			TradingCallService.delivery(sellerId, orderId, false);
			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall(paytype,
						thirdTradingId.toString(), userId.intValue());

				Thread.sleep(3000);

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;
				BigDecimal tempCouponAmount = BigDecimal.ZERO;

				// 已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);

					BigDecimal deductedCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						deductedCouponAmount = order.getOrderPo()
								.getYmtCouponAmount()
								.subtract(tempCouponAmount);
					}

					else {
						deductedCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount(), Utils
												.zeroIfNull(order.getOrderPo()
														.getYmtCouponAmount()));

						tempCouponAmount = tempCouponAmount
								.add(deductedCouponAmount);
					}

					expectedRefundBillPo
							.setDeductedCouponAmount(deductedCouponAmount);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					
					expectUserRefundFundDetailPo.setOrderId(orderId);
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 商家扣款流水记录
					AccountEntry sellerAccountEntry = RefundService
							.getAccountEntry(sellerId, orderId + "_"
									+ refundBillNo + "_1", refundBillNo);

					DataUtil.verifyDecimalEquals(
							refund.getRefundAmount()
									.add(expectedRefundBillPo
											.getDeductedCouponAmount())
									.divide(new BigDecimal(-1)),
							sellerAccountEntry.getAmount(),
							String.format(
									"退款单号 refundBillNo : %s 校验商家 sellerId : %s 账户退款 扣款 流水记录 ",
									refundBillNo, sellerId));
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@SuppressWarnings("static-access")
	@Test
	@Category({ P1.class })
	@TestCase
	@Ignore
	public void Tc_AgreeRefund_011() {
		Logger.start(true, "确认收货后,商家备用金不够,退货退款结算失败");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			Long sellerId = order.getSellerId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), BigDecimal.ZERO,
					placeOrderResp.getTradingId(), "13");

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall("13",
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			// 发货
			TradingCallService.delivery(sellerId, orderId, false);
			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);

			// 对结算单进行结算
			// settlesellerIncome(orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			BigDecimal refundAmount = applyRefundReq.getSalesRefundInfoList()
					.get(0).getRefundAmount();

			String refundBillNo = applyRefundReq.getSalesRefundInfoList()
					.get(0).getRefundBillNo();

			// 重置商家余额
			AccountCallServiceV2.resetAccount(
					AccountCallServiceV2.getAccountId(sellerId.intValue()),
					refundAmount.subtract(BigDecimal.ONE), BigDecimal.ZERO);

			salesrefundsuccessReq.setOrderId(orderId);
			salesrefundsuccessReq.setRefundBillNo(refundBillNo);
			salesrefundsuccessCall.setData(salesrefundsuccessReq);
			salesrefundsuccessCall.callService();
			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			Thread.sleep(3000);

			SalesRefundInfoVo refund = applyRefundReq.getSalesRefundInfoList()
					.get(0);

			refundBillNo = refund.getRefundBillNo();

			RefundBillPo expectedRefundBillPo = new RefundBillPo();

			expectedRefundBillPo.setRefundBillNo(refundBillNo);
			expectedRefundBillPo.setCatalogId(refund.getCatalogId());
			expectedRefundBillPo.setTotalAmount(refund.getRefundAmount());

			expectedRefundBillPo.setTopspeedRefund(false);
			expectedRefundBillPo.setAfterReceiving(true);
			expectedRefundBillPo.setRefundStatus(0);

			expectedRefundBillPo.setRefundBillStatus(10);

			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			RefundService.verifyRefundBillDb(expectedRefundBillPo,
					actualRefundBillPo);

			UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
					.selectUserRefundFundDetailByBizno(refundBillNo);

			UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

			expectUserRefundFundDetailPo.setAccountRefundStatus(-1);
			expectUserRefundFundDetailPo.setThirdpartyRefundStatus(1);

			expectUserRefundFundDetailPo.setRetryTimes(0);
			// expectUserRefundFundDetailPo.setMemo("9002:可用余额不足");

			RefundService.verifyUserRefundFundDetailDb(
					expectUserRefundFundDetailPo, userRefundFundDetailPo);

			// 重置商家余额
			AccountCallServiceV2.resetAccount(
					AccountCallServiceV2.getAccountId(sellerId.intValue()),
					new BigDecimal(9999999), BigDecimal.ZERO);

			// 退款补偿
			RefundService.retryRefund();

			// 退款补偿
			RefundService.retryRefund();

			Logger.comment("退款补偿");

			Thread.sleep(3000);

			orderShardingWapper.shardingSqlSession.clearCache();

			userRefundFundDetailPo = orderShardingWapper
					.selectUserRefundFundDetailByBizno(refundBillNo);

			expectUserRefundFundDetailPo.setAccountRefundStatus(-1);
			expectUserRefundFundDetailPo.setThirdpartyRefundStatus(3);
			expectUserRefundFundDetailPo.setRetryTimes(1);
			// expectUserRefundFundDetailPo.setMemo("0");

			RefundService.verifyUserRefundFundDetailDb(
					expectUserRefundFundDetailPo, userRefundFundDetailPo);

			actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			expectedRefundBillPo.setRefundStatus(0);

			RefundService.verifyRefundBillDb(expectedRefundBillPo,
					actualRefundBillPo);

			/*
			 * //退余额校验余额账户退款流水记录 AccountEntry accountEntry =
			 * RefundService.getAccountEntry(userId, refundBillNo,
			 * refundBillNo);
			 * 
			 * DataUtil.verifyDecimalEquals(refund.getRefundAmount(),
			 * accountEntry .getAmount(), String.format(
			 * "退款单号 refundBillNo : %s 校验余额退款流水记录 ", refundBillNo));
			 */

			// 商家扣款流水记录
			AccountEntry sellerAccountEntry = RefundService.getAccountEntry(
					sellerId, refundBillNo, refundBillNo);

			DataUtil.verifyDecimalEquals(
					refund.getRefundAmount()
							.add(Utils.zeroIfNull(expectedRefundBillPo
									.getDeductedCouponAmount()))
							.divide(new BigDecimal(-1)),
					sellerAccountEntry.getAmount(),
					String.format(
							"退款单号 refundBillNo : %s 校验商家 sellerId : %s 账户退款 扣款 流水记录 ",
							refundBillNo, sellerId));

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_012() {
		Logger.start(true, "下单使用分别使用平台券优惠券，商家优惠券，多个商品依次全部退款，"
				+ "校验平台券金额按比例退，商家优惠券金额不退");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			Long orderId = order.getOrderId();

			// 支付
			TradingCallService.payOrder(placeOrderResp.getUserId(),
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(5000);

			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);
					BigDecimal totalAmount = refund.getRefundAmount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refund.getRefundAmount())) {

						accountAmount = refund.getRefundAmount();
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = totalAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(BigDecimal.ZERO);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = order.getOrderPo()
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount(), Utils
												.zeroIfNull(order.getOrderPo()
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P3.class })
	@TestCase
	public void Tc_AgreeRefund_013() {
		Logger.start(true, "一个订单一个商品,订单已发货，货全部取消,还有金额没退的。订单状态不变");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);
			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = new BigDecimal(70);

			String paytype = "13";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			// 发货
			TradingCallService.delivery(order.getSellerId(), orderId, false);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);

			// 货退完，款还有部分未退
			applyRefundReq.getSalesRefundInfoList().forEach(
					re -> re.setRefundAmount(re.getRefundAmount().subtract(
							BigDecimal.TEN)));

			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(4000);

			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), userId.intValue());

			Thread.sleep(3000);

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper.selectOrderbyOrderId(orderId);

			Logger.verifyEquals(3, orderPo.getOrderStatus(), "校验订单状态不变");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_014() {
		Logger.start(true, "余额全款支付。确认收货前,订单极速退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			Long userId = placeOrderResp.getUserId();
			Long orderId = order.getOrderId();

			// 支付
			TradingCallService.payOrder(placeOrderResp.getUserId(),
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);
			salesrefundsuccessReq.setTopspeedRefund(true);

			int i = 0;
			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(5000);

			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			if (salesrefundsuccessCall.getString("success").equals("true")) {
				
				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(j);
					BigDecimal totalAmount = refund.getRefundAmount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refund.getRefundAmount())) {

						accountAmount = refund.getRefundAmount();
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = totalAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(BigDecimal.ZERO);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = order.getOrderPo()
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount(), Utils
												.zeroIfNull(order.getOrderPo()
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo.setRefundBillStatus(10);
					expectedRefundBillPo.setNoSettlementCouponAmount(noSettlementCouponAmount);

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					expectedRefundBillPo.setTopspeedRefund(true);
					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					DataUtil.verifyDecimalEquals(
							RefundService.getAccountEntry(userId, orderId + "_" + refundBillNo + "_1",
									refundBillNo).getAmount(),
							refund.getRefundAmount(), "校验取消订单退款余额入账流水金额");
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_015() {
		Logger.start(true, "退款退货,校验库存返还情况");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(true, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			Long orderId = order.getOrderId();

			// 支付
			TradingCallService.payOrder(placeOrderResp.getUserId(),
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			List<OrderDetailPo> orderDetailPoList = order
					.getOrderDetailPoList();

			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			Map<String, Integer> beforeStockNums = new HashMap<String, Integer>();

			for (OrderDetailPo orderDetailPo : orderDetailPoList) {

				String proId = orderDetailPo.getProductId();
				String calId = orderDetailPo.getCatalogId();

				int stockNum = TradingProductVo.getStockNum(proId, calId,
						false);

				beforeStockNums.put(calId, stockNum);

				Logger.comment(String.format(
						"proId：%s,calalogId:%s 下单之后的库存:%s", proId, calId,
						stockNum));
			}

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(5000);

			for (OrderDetailPo orderDetailPo : orderDetailPoList) {

				String proId = orderDetailPo.getProductId();
				String calId = orderDetailPo.getCatalogId();

				int stockNum = TradingProductVo.getStockNum(proId, calId,
						false);

				Logger.comment(String.format(
						"proId：%s,calalogId:%s 下单之后的库存:%s", proId, calId,
						stockNum));

				Logger.verifyEquals(
						beforeStockNums.get(calId)
								+ orderDetailPo.getProductCount(), stockNum,
						"校验退款完成会后商品库存返还");
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_027() {
		Logger.start(true, "使用了预付卡订单，全余额支付。确认收货前,订单多个商品依次全部全款退款");
		try {
			TradingServiceResp placeOrderResp = PrepaidCardService
					.placeOrder2(false);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			Long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = totalPrice;

			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			TradingCallService.payOrder(userId, useAccountAmount, tradingId,
					payType);

			// 卖家接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 申请退款
			ApplyRefundReq refundReq = RefundService.applyRefund(order);

			BigDecimal totalRefundAmount = refundReq.getSalesRefundInfoList()
					.stream().map(SalesRefundInfoVo::getRefundAmount)
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			BigDecimal beforeAmount = AccountCallServiceV2.getAccountBalance(
					userId.intValue(), 1);

			salesrefundsuccessReq.setOrderId(orderId);

			for (int i = 0; i < refundReq.getSalesRefundInfoList().size(); i++) {

				SalesRefundInfoVo salesRefundInfoVo = refundReq
						.getSalesRefundInfoList().get(i);

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());

				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("退该订单号 %s 第%s件商品", orderId, i + 1));
				salesrefundsuccessCall.callService();

			}

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			// 订单表(order)
			OrderPo ymtOrders = orderShardingWapper
					.selectOrderbyOrderId(orderId);

			BigDecimal totalCard = BigDecimal.ZERO;

			for (SalesRefundInfoVo refundInfoVo : refundReq
					.getSalesRefundInfoList()) {

				totalCard = PrepaidCardService.getCardEntry(userId.intValue(),
						refundInfoVo.getRefundBillNo()).add(totalCard);
			}

			DataUtil.verifyDecimalEquals(ymtOrders.getCardAmount(), totalCard,
					"校验取消订单退回的预付卡金额");

			BigDecimal afterAmount = AccountCallServiceV2.getAccountBalance(
					userId.intValue(), 1);

			DataUtil.verifyDecimalEquals(
					totalRefundAmount.subtract(ymtOrders.getCardAmount()),
					afterAmount.subtract(beforeAmount), "校验取消订单退回的资金账户金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_028() {
		Logger.start(true, "使用了预付卡订单，余额+第三方支付宝组合支付。确认收货前,订单多个商品依次全部全款退款");
		try {

			TradingServiceResp placeOrderResp = PrepaidCardService
					.placeOrder2(true);

			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);
			// 卖家接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			for (int i = 0; i < applyRefundReq.getSalesRefundInfoList().size(); i++) {

				SalesRefundInfoVo salesRefundInfoBean = applyRefundReq
						.getSalesRefundInfoList().get(i);

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoBean
						.getRefundBillNo());

				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("退该订单号 %s 第%s件商品", orderId, i + 1));
				salesrefundsuccessCall.callService();

			}

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			Thread.sleep(4000);

			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), userId.intValue());

			Thread.sleep(3000);

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;
			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			// 数据库验证
			for (int j = 0; j < applyRefundReq.getSalesRefundInfoList().size(); j++) {

				SalesRefundInfoVo refund = applyRefundReq
						.getSalesRefundInfoList().get(j);

				String refundBillNo = refund.getRefundBillNo();
				RefundBillPo actualRefundBillPo = orderShardingWapper
						.selectRefundBillByBillNo(refundBillNo);

				OrderDetailPo orderDetailPo = orderShardingWapper
						.selectOrderDetailbyOrderId(orderId).get(j);

				cardAmount = actualRefundBillPo.getCardAmount();

				// 退款，优先退 预付卡
				if (Utils.isBiggerThanOrEqual(
						cardPaidAmount.subtract(refundedCardAmount),
						refund.getRefundAmount()))
					cardAmount = refund.getRefundAmount();
				else
					cardAmount = cardPaidAmount.subtract(refundedCardAmount);

				refundedCardAmount = refundedCardAmount.add(cardAmount);

				// 退款减去 退 预付卡
				BigDecimal refundAmount = refund.getRefundAmount().subtract(
						cardAmount);

				// 余额支付大于退款金额，先退余额
				if (Utils.isBiggerThanOrEqual(
						accountPaidAmount.subtract(refundedAccountAmount),
						refundAmount)) {

					accountAmount = refundAmount;
				} else {

					accountAmount = accountPaidAmount
							.subtract(refundedAccountAmount);
					thirdpartyAmount = refundAmount.subtract(accountAmount);
				}

				refundedAccountAmount = refundedAccountAmount
						.add(accountAmount);

				RefundBillPo expectedRefundBillPo = new RefundBillPo();

				expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
				expectedRefundBillPo.setOrderId(orderId);
				expectedRefundBillPo.setSellerId(orderPo.getSellerId());
				expectedRefundBillPo.setUserId(orderPo.getUserId());
				expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
				expectedRefundBillPo.setProductCount(orderDetailPo
						.getProductCount());
				expectedRefundBillPo.setAccountAmount(accountAmount);
				expectedRefundBillPo.setCardAmount(cardAmount);
				expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
				expectedRefundBillPo.setRefundBillNo(refundBillNo);
				expectedRefundBillPo.setCatalogId(refund.getCatalogId());
				expectedRefundBillPo.setTotalAmount(refund.getRefundAmount());
				expectedRefundBillPo.setTopspeedRefund(false);
				expectedRefundBillPo.setAfterReceiving(false);
				expectedRefundBillPo.setRefundStatus(1);
				expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
				BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

				if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

					noSettlementCouponAmount = orderPo.getYmtCouponAmount()
							.subtract(tempNoSettlementCouponAmount);
				}

				else {
					noSettlementCouponAmount = RefundService
							.devideThenMultiply(
									refund.getRefundAmount(),
									order.getOrderPayableAmount().add(
											orderPo.getCardAmount()), Utils
											.zeroIfNull(orderPo
													.getYmtCouponAmount()));

					tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
							.add(noSettlementCouponAmount);
				}

				expectedRefundBillPo
						.setNoSettlementCouponAmount(noSettlementCouponAmount);

				expectedRefundBillPo.setRefundBillStatus(10);

				RefundService.verifyRefundBillDb(expectedRefundBillPo,
						actualRefundBillPo);

				if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
					continue;

				// 用户退款资金详情表（user_refund_fund_detail）
				UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
						.selectUserRefundFundDetailByBizno(refundBillNo);

				UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

				expectUserRefundFundDetailPo.setPaymentId(Long
						.valueOf(thirdTradingId));

				expectUserRefundFundDetailPo.setBizType(1);

				expectUserRefundFundDetailPo.setAccountAmount(accountAmount);

				int accountRefundStatus = -1;

				if (Utils.isBiggerThan(
						expectUserRefundFundDetailPo.getAccountAmount(),
						BigDecimal.ZERO)) {

					accountRefundStatus = 4;

					// 退余额校验余额账户退款流水记录
					AccountEntry accountEntry = RefundService.getAccountEntry(
							userId, refundBillNo, refundBillNo);

					DataUtil.verifyDecimalEquals(expectUserRefundFundDetailPo
							.getAccountAmount(), accountEntry.getAmount(),
							String.format("退款单号 refundBillNo : %s 校验余额退款流水记录 ",
									refundBillNo));
				}

				expectUserRefundFundDetailPo
						.setAccountRefundStatus(accountRefundStatus);

				expectUserRefundFundDetailPo.setThirdpartyAmount(refundAmount
						.subtract(accountAmount));

				int thirdpartyRefundStatus = -1;

				if (Utils.isBiggerThan(
						expectUserRefundFundDetailPo.getThirdpartyAmount(),
						BigDecimal.ZERO)) {
					thirdpartyRefundStatus = 4;

				}
				expectUserRefundFundDetailPo
						.setThirdpartyRefundStatus(thirdpartyRefundStatus);
				expectUserRefundFundDetailPo
						.setThirdpartyDiscount(BigDecimal.ZERO);
				expectUserRefundFundDetailPo.setRetryTimes(0);
				expectUserRefundFundDetailPo.setMemo("0");

				RefundService.verifyUserRefundFundDetailDb(
						expectUserRefundFundDetailPo, userRefundFundDetailPo);
			}

			BigDecimal totalCard = BigDecimal.ZERO;

			for (SalesRefundInfoVo refundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				totalCard = PrepaidCardService.getCardEntry(userId.intValue(),
						refundInfoVo.getRefundBillNo()).add(totalCard);
			}

			DataUtil.verifyDecimalEquals(orderPo.getCardAmount(), totalCard,
					"校验取消订单退回的预付卡金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_029() {
		Logger.start(true, "使用了预付卡订单，余额+第三方支付宝组合支付。确认收货前,订单部分退款的金额超过余额支付的部分");
		try {

			TradingServiceResp placeOrderResp = PrepaidCardService
					.placeOrder2(false);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long sellerId = order.getSellerId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(8);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(2000);
			// 卖家接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);

			applyRefundReq.getSalesRefundInfoList().remove(1);
			applyRefundReq.getSalesRefundInfoList().remove(1);

			applyRefundReq.getSalesRefundInfoList().get(0)
					.setRefundAmount(useAccountAmount.add(BigDecimal.TEN));

			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			for (int i = 0; i < applyRefundReq.getSalesRefundInfoList().size(); i++) {

				SalesRefundInfoVo salesRefundInfoBean = applyRefundReq
						.getSalesRefundInfoList().get(i);

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoBean
						.getRefundBillNo());

				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("退该订单号 %s 第%s件商品", orderId, i + 1));
				salesrefundsuccessCall.callService();

			}

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			Thread.sleep(3000);

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			// 数据库验证
			for (int j = 0; j < applyRefundReq.getSalesRefundInfoList().size(); j++) {

				SalesRefundInfoVo refund = applyRefundReq
						.getSalesRefundInfoList().get(j);

				String refundBillNo = refund.getRefundBillNo();

				RefundBillPo actualRefundBillPo = orderShardingWapper
						.selectRefundBillByBillNo(refundBillNo);

				OrderDetailPo orderDetailPo = orderShardingWapper
						.selectOrderDetailbyOrderId(orderId).get(j);

				cardAmount = actualRefundBillPo.getCardAmount();

				// 退款，优先退 预付卡
				if (Utils.isBiggerThanOrEqual(
						cardPaidAmount.subtract(refundedCardAmount),
						refund.getRefundAmount()))
					cardAmount = refund.getRefundAmount();
				else
					cardAmount = cardPaidAmount.subtract(refundedCardAmount);

				refundedCardAmount = refundedCardAmount.add(cardAmount);

				// 退款减去 退 预付卡
				BigDecimal refundAmount = refund.getRefundAmount().subtract(
						cardAmount);

				// 余额支付大于退款金额，先退余额
				if (Utils.isBiggerThanOrEqual(
						accountPaidAmount.subtract(refundedAccountAmount),
						refundAmount)) {

					accountAmount = refundAmount;
				} else {

					accountAmount = accountPaidAmount
							.subtract(refundedAccountAmount);
					thirdpartyAmount = refundAmount.subtract(accountAmount);
				}

				refundedAccountAmount = refundedAccountAmount
						.add(accountAmount);

				RefundBillPo expectedRefundBillPo = new RefundBillPo();

				expectedRefundBillPo.setFreight(BigDecimal.ZERO);
				expectedRefundBillPo.setOrderId(orderId);
				expectedRefundBillPo.setSellerId(orderPo.getSellerId());
				expectedRefundBillPo.setUserId(orderPo.getUserId());
				expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
				expectedRefundBillPo.setProductCount(orderDetailPo
						.getProductCount());
				expectedRefundBillPo.setAccountAmount(accountAmount);
				expectedRefundBillPo.setCardAmount(cardAmount);
				expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
				expectedRefundBillPo.setRefundBillNo(refundBillNo);
				expectedRefundBillPo.setCatalogId(refund.getCatalogId());
				expectedRefundBillPo.setTotalAmount(refund.getRefundAmount());
				expectedRefundBillPo.setTopspeedRefund(false);
				expectedRefundBillPo.setAfterReceiving(false);
				expectedRefundBillPo.setRefundStatus(1);
				expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
				expectedRefundBillPo
						.setNoSettlementCouponAmount(BigDecimal.ZERO);
				expectedRefundBillPo.setRefundBillStatus(10);

				RefundService.verifyRefundBillDb(expectedRefundBillPo,
						actualRefundBillPo);

				DataUtil.verifyDecimalEquals(cardAmount, PrepaidCardService
						.getCardEntry(userId.intValue(), applyRefundReq
								.getSalesRefundInfoList().get(0)
								.getRefundBillNo()), "校验退回的预付卡金额");
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_030() {
		Logger.start(true, "使用了预付卡订单，余额+第三方支付宝组合支付。确认收货前,订单部分退款的金额小于余额支付的部分");
		try {

			TradingServiceResp placeOrderResp = PrepaidCardService
					.placeOrder2(false);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long sellerId = order.getSellerId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(2000);
			// 卖家接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);

			applyRefundReq.getSalesRefundInfoList().remove(1);
			applyRefundReq.getSalesRefundInfoList().remove(1);

			applyRefundReq
					.getSalesRefundInfoList()
					.get(0)
					.setRefundAmount(
							useAccountAmount.subtract(new BigDecimal(14)));

			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			for (int i = 0; i < applyRefundReq.getSalesRefundInfoList().size(); i++) {

				SalesRefundInfoVo salesRefundInfoBean = applyRefundReq
						.getSalesRefundInfoList().get(i);

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoBean
						.getRefundBillNo());

				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("退该订单号 %s 第%s件商品", orderId, i + 1));
				salesrefundsuccessCall.callService();

			}

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			Thread.sleep(3000);

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			// 数据库验证
			for (int j = 0; j < applyRefundReq.getSalesRefundInfoList().size(); j++) {

				SalesRefundInfoVo refund = applyRefundReq
						.getSalesRefundInfoList().get(j);

				String refundBillNo = refund.getRefundBillNo();

				RefundBillPo actualRefundBillPo = orderShardingWapper
						.selectRefundBillByBillNo(refundBillNo);

				OrderDetailPo orderDetailPo = orderShardingWapper
						.selectOrderDetailbyOrderId(orderId).get(j);

				cardAmount = actualRefundBillPo.getCardAmount();

				// 退款，优先退 预付卡
				if (Utils.isBiggerThanOrEqual(
						cardPaidAmount.subtract(refundedCardAmount),
						refund.getRefundAmount()))
					cardAmount = refund.getRefundAmount();
				else
					cardAmount = cardPaidAmount.subtract(refundedCardAmount);

				refundedCardAmount = refundedCardAmount.add(cardAmount);

				// 退款减去 退 预付卡
				BigDecimal refundAmount = refund.getRefundAmount().subtract(
						cardAmount);

				// 余额支付大于退款金额，先退余额
				if (Utils.isBiggerThanOrEqual(
						accountPaidAmount.subtract(refundedAccountAmount),
						refundAmount)) {

					accountAmount = refundAmount;
				} else {

					accountAmount = accountPaidAmount
							.subtract(refundedAccountAmount);
					thirdpartyAmount = refundAmount.subtract(accountAmount);
				}

				refundedAccountAmount = refundedAccountAmount
						.add(accountAmount);

				RefundBillPo expectedRefundBillPo = new RefundBillPo();

				expectedRefundBillPo.setFreight(BigDecimal.ZERO);
				expectedRefundBillPo.setOrderId(orderId);
				expectedRefundBillPo.setSellerId(orderPo.getSellerId());
				expectedRefundBillPo.setUserId(orderPo.getUserId());
				expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
				expectedRefundBillPo.setProductCount(orderDetailPo
						.getProductCount());
				expectedRefundBillPo.setAccountAmount(accountAmount);
				expectedRefundBillPo.setCardAmount(cardAmount);
				expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
				expectedRefundBillPo.setRefundBillNo(refundBillNo);
				expectedRefundBillPo.setCatalogId(refund.getCatalogId());
				expectedRefundBillPo.setTotalAmount(refund.getRefundAmount());
				expectedRefundBillPo.setTopspeedRefund(false);
				expectedRefundBillPo.setAfterReceiving(false);
				expectedRefundBillPo.setRefundStatus(1);
				expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
				expectedRefundBillPo
						.setNoSettlementCouponAmount(BigDecimal.ZERO);
				expectedRefundBillPo.setRefundBillStatus(10);

				RefundService.verifyRefundBillDb(expectedRefundBillPo,
						actualRefundBillPo);

				DataUtil.verifyDecimalEquals(cardAmount, PrepaidCardService
						.getCardEntry(userId.intValue(), applyRefundReq
								.getSalesRefundInfoList().get(0)
								.getRefundBillNo()), "校验退回的预付卡金额");
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_035() {
		Logger.start(true, "使用微信支付立减。确认收货前,订单多个商品依次全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(4000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(3000);

					// 订单表(order)
					OrderPo orderPo = orderShardingWapper
							.selectOrderbyOrderId(orderId);
					BigDecimal accountPaidAmount = orderPo
							.getAccountPaidAmount();
					BigDecimal cardPaidAmount = orderPo.getCardAmount();
					BigDecimal refundedAccountAmount = BigDecimal.ZERO;

					BigDecimal accountAmount = BigDecimal.ZERO;
					BigDecimal thirdpartyAmount = BigDecimal.ZERO;
					BigDecimal cardAmount = BigDecimal.ZERO;

					// 已退款的预付卡金额
					BigDecimal refundedCardAmount = BigDecimal.ZERO;

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}

				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_036() {
		Logger.start(true, "使用微信支付立减。确认收货前,订单退一个商品全款退款,然后再确认收货");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleApplyRefundReq(order);
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(4000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(3000);

					// 订单表(order)
					OrderPo orderPo = orderShardingWapper
							.selectOrderbyOrderId(orderId);
					BigDecimal accountPaidAmount = orderPo
							.getAccountPaidAmount();
					BigDecimal cardPaidAmount = orderPo.getCardAmount();
					BigDecimal refundedAccountAmount = BigDecimal.ZERO;

					BigDecimal accountAmount = BigDecimal.ZERO;
					BigDecimal thirdpartyAmount = BigDecimal.ZERO;
					BigDecimal cardAmount = BigDecimal.ZERO;

					// 已退款的预付卡金额
					BigDecimal refundedCardAmount = BigDecimal.ZERO;

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				
				break;
			}

			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_037() {
		Logger.start(true, "使用微信支付立减。确认收货前,订单多个商品依次部分退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(4000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(3000);

					// 订单表(order)
					OrderPo orderPo = orderShardingWapper
							.selectOrderbyOrderId(orderId);
					BigDecimal accountPaidAmount = orderPo
							.getAccountPaidAmount();
					BigDecimal cardPaidAmount = orderPo.getCardAmount();
					BigDecimal refundedAccountAmount = BigDecimal.ZERO;

					BigDecimal accountAmount = BigDecimal.ZERO;
					BigDecimal thirdpartyAmount = BigDecimal.ZERO;
					BigDecimal cardAmount = BigDecimal.ZERO;

					// 已退款的预付卡金额
					BigDecimal refundedCardAmount = BigDecimal.ZERO;

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}

				i++;
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_038() {
		Logger.start(true, "使用微信支付立减。确认收货后,订单多个商品依次全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(4000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(3000);

					// 订单表(order)
					OrderPo orderPo = orderShardingWapper
							.selectOrderbyOrderId(orderId);
					BigDecimal accountPaidAmount = orderPo
							.getAccountPaidAmount();
					BigDecimal cardPaidAmount = orderPo.getCardAmount();
					BigDecimal refundedAccountAmount = BigDecimal.ZERO;

					BigDecimal accountAmount = BigDecimal.ZERO;
					BigDecimal thirdpartyAmount = BigDecimal.ZERO;
					BigDecimal cardAmount = BigDecimal.ZERO;

					// 已退款的预付卡金额
					BigDecimal refundedCardAmount = BigDecimal.ZERO;

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}

				i++;
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_039() {
		Logger.start(true, "使用微信支付立减。确认收货后,订单多个商品依次部分退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = BigDecimal.ZERO;

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(4000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(3000);

					// 订单表(order)
					OrderPo orderPo = orderShardingWapper
							.selectOrderbyOrderId(orderId);
					BigDecimal accountPaidAmount = orderPo
							.getAccountPaidAmount();
					BigDecimal cardPaidAmount = orderPo.getCardAmount();
					BigDecimal refundedAccountAmount = BigDecimal.ZERO;

					BigDecimal accountAmount = BigDecimal.ZERO;
					BigDecimal thirdpartyAmount = BigDecimal.ZERO;
					BigDecimal cardAmount = BigDecimal.ZERO;

					// 已退款的预付卡金额
					BigDecimal refundedCardAmount = BigDecimal.ZERO;

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, refundBillNo,
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}

				i++;
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_040() {
		Logger.start(true, "使用余额+微信支付立减。确认收货后,订单多个商品依次全款退款");
		try {
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithThreeProcutInTwoOrder(false, BigDecimal.ZERO,
							userId, LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			BigDecimal useAccountAmount = new BigDecimal(10);

			String paytype = "15";

			// 支付
			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), paytype);

			BigDecimal discountAmount = new BigDecimal(10);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(paytype,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue(), discountAmount);

			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			int i = 0;
			
			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					List<OrderDetailPo> orderDetailList = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId);
					BigDecimal thirdPartyDiscount = orderDetailList.get(i)
							.getThirdpartyDiscount();
					
					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("15",
							thirdTradingId.toString(), userId.intValue(),
							thirdPartyDiscount);

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);
					BigDecimal thirdpartyDiscount = orderDetailPo
							.getThirdpartyDiscount();

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setProductCount(orderDetailPo
							.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setNoSettlementCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount
							.subtract(thirdpartyDiscount));

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo.getAccountAmount(),
								accountEntry.getAmount(), String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount.subtract(
									accountAmount).subtract(thirdpartyDiscount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(thirdpartyDiscount);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);
					
					orderShardingWapper.clearCache();
					
					if (null == expectRefundFundPo.getFreight())
						expectRefundFundPo.setFreight(orderDetailPo.getFreight());
					else
						expectRefundFundPo.setFreight(expectRefundFundPo
								.getFreight().add(orderDetailPo.getFreight()));
					
					expectRefundFundPo.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo.setThirdpartyDiscount(expectRefundFundPo
							.getThirdpartyDiscount().add(
									userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo.setUserAccountAmount(expectRefundFundPo
							.getUserAccountAmount().add(
									userRefundFundDetailPo.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				
				i++;
			}

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_041() {
		Logger.start(true, "余额支付定金，定金订单支付全款后，验证定金余额退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			long thirdTradingId = TradingCallService.payEngageOrder(userId,
					earnestAmount, tradingId);

			TradingCallService.payFullPaidOrder(userId, orderId);

			Logger.comment("前置数据准备结束");
			
			Thread.sleep(3000);

			// 用户退款资金详情表（user_refund_fund_detail）
			UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
					.selectUserRefundFundDetailByBizno(String.valueOf(orderId));

			UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

			expectUserRefundFundDetailPo.setPaymentId(Long
					.valueOf(thirdTradingId));

			expectUserRefundFundDetailPo.setBizType(5);

			expectUserRefundFundDetailPo.setAccountAmount(earnestAmount);
			expectUserRefundFundDetailPo.setAccountRefundStatus(4);
			expectUserRefundFundDetailPo.setOrderId(orderId);

			expectUserRefundFundDetailPo.setThirdpartyAmount(BigDecimal.ZERO);

			expectUserRefundFundDetailPo.setThirdpartyRefundStatus(-1);
			expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
			expectUserRefundFundDetailPo.setRetryTimes(0);
			expectUserRefundFundDetailPo.setMemo("0");

			RefundService.verifyUserRefundFundDetailDb(
					expectUserRefundFundDetailPo, userRefundFundDetailPo);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_042() {
		Logger.start(true, "第三方支付定金，定金订单支付全款后，验证定金第三方退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			// 第三方支付定金
			Long thirdTradingId = TradingCallService.payOrder(userId,
					BigDecimal.ZERO, tradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					earnestAmount.toString(), (int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			// 支付全款
			TradingCallService.payFullPaidOrder(userId, orderId);
			Thread.sleep(5000);

			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), (int) userId);

			Logger.comment("前置数据准备结束");
			
			Thread.sleep(3000);

			// 用户退款资金详情表（user_refund_fund_detail）
			UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
					.selectUserRefundFundDetailByBizno(String.valueOf(orderId));

			BigDecimal accountAmount = BigDecimal.ZERO;

			UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

			expectUserRefundFundDetailPo.setPaymentId(Long
					.valueOf(thirdTradingId));

			expectUserRefundFundDetailPo.setBizType(5);

			expectUserRefundFundDetailPo.setAccountAmount(BigDecimal.ZERO);
			expectUserRefundFundDetailPo.setOrderId(orderId);
			expectUserRefundFundDetailPo.setAccountRefundStatus(-1);

			expectUserRefundFundDetailPo.setThirdpartyAmount(earnestAmount
					.subtract(accountAmount).subtract(BigDecimal.ZERO));

			expectUserRefundFundDetailPo.setThirdpartyRefundStatus(4);
			expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
			expectUserRefundFundDetailPo.setRetryTimes(0);
			expectUserRefundFundDetailPo.setMemo("0");

			RefundService.verifyUserRefundFundDetailDb(
					expectUserRefundFundDetailPo, userRefundFundDetailPo);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_043() {
		Logger.start(true, "第三方+余额支付定金，定金订单支付全款后，验证定金第三方+余额退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();
			BigDecimal accountAmount = BigDecimal.ONE;

			// 第三方支付定金
			Long thirdTradingId = TradingCallService.payOrder(userId,
					accountAmount, tradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					earnestAmount.subtract(accountAmount).toString(),
					(int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			// 支付全款
			TradingCallService.payFullPaidOrder(userId, orderId);
			Thread.sleep(5000);

			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), (int) userId);

			Logger.comment("前置数据准备结束");
			
			Thread.sleep(3000);

			// 用户退款资金详情表（user_refund_fund_detail）
			UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
					.selectUserRefundFundDetailByBizno(String.valueOf(orderId));

			UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

			expectUserRefundFundDetailPo.setPaymentId(Long
					.valueOf(thirdTradingId));

			expectUserRefundFundDetailPo.setBizType(5);

			expectUserRefundFundDetailPo.setAccountAmount(accountAmount);
			expectUserRefundFundDetailPo.setOrderId(orderId);
			expectUserRefundFundDetailPo.setAccountRefundStatus(4);

			expectUserRefundFundDetailPo.setThirdpartyAmount(earnestAmount
					.subtract(accountAmount).subtract(BigDecimal.ZERO));

			expectUserRefundFundDetailPo.setThirdpartyRefundStatus(4);
			expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
			expectUserRefundFundDetailPo.setRetryTimes(0);
			expectUserRefundFundDetailPo.setMemo("0");

			RefundService.verifyUserRefundFundDetailDb(
					expectUserRefundFundDetailPo, userRefundFundDetailPo);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_044() {
		Logger.start(true, "第三方+余额支付全款后。确认收货前,订单多个商品依次全部退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			TradingCallService.payEngageOrder(userId, earnestAmount, tradingId);

			List<Long> bookingConfirmOrderIds = new ArrayList<Long>();
			bookingConfirmOrderIds.add(orderId);

			TradingServiceResp fullPaidResp = TradingPlaceEngageOrderCallService
					.placeOrderWithBookingConfirmOrderIds(bookingConfirmOrderIds);
			Order order = fullPaidResp
					.getOrderList()
					.stream()
					.filter(o -> o.getOrderPo().getBookingPromotionAmount() != null)
					.collect(Collectors.toList()).get(0);
			BigDecimal useAccountAmount = BigDecimal.ZERO;
			long fullPaidTradingId = fullPaidResp.getTradingId();

			// 支付全款
			Long thirdTradingId = TradingCallService.payOrder(userId,
					useAccountAmount, fullPaidTradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					fullPaidResp.getPayableAmount().subtract(useAccountAmount)
							.toString(), (int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), (int) userId);

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;
				
				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				//已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;

				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);
					
					OrderDetailPo orderDetailPo = orderShardingWapper.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();
					
					//退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount.subtract(refundedCardAmount);
					
					refundedCardAmount = refundedCardAmount.add(cardAmount);

					//退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount().subtract(
							cardAmount);
					
					//余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}
					
					refundedAccountAmount = refundedAccountAmount.add(accountAmount);
					
					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount().add(orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;
					
					//用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						//退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService.getAccountEntry(
								userId, refundBillNo, refundBillNo);

						DataUtil.verifyDecimalEquals(expectUserRefundFundDetailPo
								.getAccountAmount(), accountEntry.getAmount(),
								String.format("退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo.setThirdpartyAmount(refundAmount
							.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo, userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_045() {
		Logger.start(true, "第三方+余额支付全款后。确认收货前,订单多个商品部分退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			TradingCallService.payEngageOrder(userId, earnestAmount, tradingId);

			List<Long> bookingConfirmOrderIds = new ArrayList<Long>();
			bookingConfirmOrderIds.add(orderId);

			TradingServiceResp fullPaidResp = TradingPlaceEngageOrderCallService
					.placeOrderWithBookingConfirmOrderIds(bookingConfirmOrderIds);
			Order order = fullPaidResp
					.getOrderList()
					.stream()
					.filter(o -> o.getOrderPo().getBookingPromotionAmount() != null)
					.collect(Collectors.toList()).get(0);
			BigDecimal useAccountAmount = BigDecimal.ZERO;
			long fullPaidTradingId = fullPaidResp.getTradingId();

			// 支付全款
			Long thirdTradingId = TradingCallService.payOrder(userId,
					useAccountAmount, fullPaidTradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					fullPaidResp.getPayableAmount().subtract(useAccountAmount)
							.toString(), (int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), (int) userId);

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;
				
				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				//已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;
				
				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);
					
					OrderDetailPo orderDetailPo = orderShardingWapper.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();
					
					//退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount.subtract(refundedCardAmount);
					
					refundedCardAmount = refundedCardAmount.add(cardAmount);

					//退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount().subtract(
							cardAmount);
					
					//余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}
					
					refundedAccountAmount = refundedAccountAmount.add(accountAmount);
					
					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount().add(orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;
					
					//用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						//退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService.getAccountEntry(
								userId, refundBillNo, refundBillNo);

						DataUtil.verifyDecimalEquals(expectUserRefundFundDetailPo
								.getAccountAmount(), accountEntry.getAmount(),
								String.format("退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo.setThirdpartyAmount(refundAmount
							.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					
					expectUserRefundFundDetailPo.setOrderId(orderId);
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo, userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_046() {
		Logger.start(true, "第三方+余额支付全款后。确认收货后,订单多个商品部分退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			TradingCallService.payEngageOrder(userId, earnestAmount, tradingId);

			List<Long> bookingConfirmOrderIds = new ArrayList<Long>();
			bookingConfirmOrderIds.add(orderId);

			TradingServiceResp fullPaidResp = TradingPlaceEngageOrderCallService
					.placeOrderWithBookingConfirmOrderIds(bookingConfirmOrderIds);

			Order order = fullPaidResp
					.getOrderList()
					.stream()
					.filter(o -> o.getOrderPo().getBookingPromotionAmount() != null)
					.collect(Collectors.toList()).get(0);
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = BigDecimal.ZERO;
			long fullPaidTradingId = fullPaidResp.getTradingId();

			// 支付全款
			Long thirdTradingId = TradingCallService.payOrder(userId,
					useAccountAmount, fullPaidTradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					fullPaidResp.getPayableAmount().subtract(useAccountAmount)
							.toString(), (int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);
			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), (int) userId);

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;
				
				// 订单表(order)
				OrderPo orderPo = orderShardingWapper
						.selectOrderbyOrderId(orderId);
				BigDecimal accountPaidAmount = orderPo.getAccountPaidAmount();
				BigDecimal cardPaidAmount = orderPo.getCardAmount();
				BigDecimal refundedAccountAmount = BigDecimal.ZERO;

				BigDecimal accountAmount = BigDecimal.ZERO;
				BigDecimal thirdpartyAmount = BigDecimal.ZERO;
				BigDecimal cardAmount = BigDecimal.ZERO;

				//已退款的预付卡金额
				BigDecimal refundedCardAmount = BigDecimal.ZERO;
				
				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);
					
					OrderDetailPo orderDetailPo = orderShardingWapper.selectOrderDetailbyOrderId(orderId).get(j);

					cardAmount = actualRefundBillPo.getCardAmount();
					
					//退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount.subtract(refundedCardAmount);
					
					refundedCardAmount = refundedCardAmount.add(cardAmount);

					//退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount().subtract(
							cardAmount);
					
					//余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(
							accountPaidAmount.subtract(refundedAccountAmount),
							refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount.subtract(accountAmount);
					}
					
					refundedAccountAmount = refundedAccountAmount.add(accountAmount);
					
					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(orderDetailPo.getFreight());
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo.setDeductedCouponAmount(BigDecimal.ZERO);
					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount().add(orderPo.getCardAmount()), Utils
												.zeroIfNull(orderPo
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;
					
					//用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getAccountAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						//退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService.getAccountEntry(
								userId, refundBillNo, refundBillNo);

						DataUtil.verifyDecimalEquals(expectUserRefundFundDetailPo
								.getAccountAmount(), accountEntry.getAmount(),
								String.format("退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo.setThirdpartyAmount(refundAmount
							.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getThirdpartyAmount(),
							BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}
					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo, userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_047() {
		Logger.start(true, "第三方+余额支付全款后。确认收货,订单多个商品全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrder = TradingPlaceEngageOrderCallService
					.placeEngageOrder(false);

			long userId = placeOrder.getUserId();
			// long sellerId = placeOrder.getOrderList().get(0).getSellerId();
			long orderId = placeOrder.getOrderList().get(0).getOrderId();
			long tradingId = placeOrder.getTradingId();
			BigDecimal earnestAmount = placeOrder.getOrderList().get(0)
					.getOrderPo().getEarnestAmount();

			TradingCallService.payEngageOrder(userId, earnestAmount, tradingId);

			List<Long> bookingConfirmOrderIds = new ArrayList<Long>();
			bookingConfirmOrderIds.add(orderId);

			TradingServiceResp fullPaidResp = TradingPlaceEngageOrderCallService
					.placeOrderWithBookingConfirmOrderIds(bookingConfirmOrderIds);

			Order order = fullPaidResp
					.getOrderList()
					.stream()
					.filter(o -> o.getOrderPo().getBookingPromotionAmount() != null)
					.collect(Collectors.toList()).get(0);
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = BigDecimal.ZERO;
			long fullPaidTradingId = fullPaidResp.getTradingId();

			// 支付全款
			Long thirdTradingId = TradingCallService.payOrder(userId,
					useAccountAmount, fullPaidTradingId, "13");
			PayGateWayCallService.notifyCall("13", thirdTradingId.toString(),
					fullPaidResp.getPayableAmount().subtract(useAccountAmount)
							.toString(), (int) userId);
			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);
			
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);

			TradingSyncService.getSyncResult(orderId);
			
			TradingCallService.confirmReceive(userId, orderId);
			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			if (salesrefundsuccessCall.getString("success").equals("true")) {

				Thread.sleep(4000);

				// 支付网关退款回调
				PayGateWayCallService.refundNotifyCall("13",
						thirdTradingId.toString(), (int) userId);

				Thread.sleep(3000);

				BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;
				// 数据库验证
				for (int j = 0; j < applyRefundReq.getSalesRefundInfoList()
						.size(); j++) {

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(j);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());

					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (j == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = order.getOrderPo()
								.getYmtCouponAmount()
								.subtract(tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(refund.getRefundAmount(),
										order.getOrderPayableAmount(), Utils
												.zeroIfNull(order.getOrderPo()
														.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo.setThirdpartyAmount(refund
							.getRefundAmount());
					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));
					expectUserRefundFundDetailPo.setAccountRefundStatus(-1);
					expectUserRefundFundDetailPo.setBizType(1);
					expectUserRefundFundDetailPo.setOrderId(orderId);

					expectUserRefundFundDetailPo.setThirdpartyAmount(refund
							.getRefundAmount());

					expectUserRefundFundDetailPo.setThirdpartyRefundStatus(4);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo
							.setAccountAmount(useAccountAmount);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);
				}
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_048() {
		Logger.start(true, "下单使用返点金额，第三方+余额支付全款后。确认收货前,订单多个商品依次全部退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAnliOrderCallService
					.placeMultiProAnlihuiOrder(BigDecimal.TEN, false, 0);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);
			
			//接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(orderDetailPo,
									refund.getRefundAmount(),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_049() {
		Logger.start(true, "下单使用返点金额,第三方+余额支付全款后。确认收货前,订单多个商品部分退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAnliOrderCallService
					.placeMultiProAnlihuiOrder(BigDecimal.TEN, false, 0);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(2000);
			
			//接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(orderDetailPo,
									refund.getRefundAmount(),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(false);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_050() {
		Logger.start(true, "第三方+余额支付全款后，使用安利会余额，确认收货后,订单多个商品部分退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAnliOrderCallService
					.placeMultiProAnlihuiOrder(BigDecimal.TEN, false, 0);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国际段发货
			TradingCallService.delivery(order.getSellerId(), orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国内段发货
			TradingCallService.delivery(order.getSellerId(), orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(orderDetailPo,
									refund.getRefundAmount(),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_051() {
		Logger.start(true, "第三方+余额支付全款,下单使用返点金额。确认收货,订单多个商品全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAnliOrderCallService
					.placeMultiProAnlihuiOrder(BigDecimal.TEN, false, 0);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国际段发货
			TradingCallService.delivery(order.getSellerId(), orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国内段发货
			TradingCallService.delivery(order.getSellerId(), orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());

					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(orderDetailPo,
									refund.getRefundAmount(),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount().add(
									actualRefundBillPo.getTotalAmount()));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_052() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，余额支付全款,确认收货,订单全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			// 用余额支付金额
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();
			
			TradingCallService.payOrder(userId, useAccountAmount, placeOrderResp.getTradingId());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService.buildStandApplyRefundReq(order);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 商品全退，加上鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum()).add(
							order.getUserAuthenticateFreightFee());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setBizType(1);
					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;
					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_053() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,确认收货,订单全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 商品全退，加上鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum()).add(
							order.getUserAuthenticateFreightFee());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_054() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,确认收货,订单部分退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order, 1);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 部分退款，无需加上鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(refund.getRefundProductNum());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_055() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,确认收货,订单部分退款，不退运费");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);
			OrderDetailPo refundedOrderDetailPo = order.getOrderDetailPoList().get(0);
			
			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleApplyRefundReq(orderId, refundedOrderDetailPo,
							BigDecimal.ZERO, 1);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 部分退款，无需加上鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(BigDecimal.ZERO);
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(refund.getRefundProductNum());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	// 坚定运费没有退
	public void Tc_AgreeRefund_056() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,确认收货,单个商品依次退款，订单全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 订单第一个商品，一个一个退
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleOneByOneApplyRefundReq(order);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			
			// 余额已经在前一个退款单全部退款
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {
				
				salesRefundInfoVo.setRefundAmount(salesRefundInfoVo
						.getRefundAmount());
				
				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(0);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 商品全退，加上鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum())
							.add(i == applyRefundReq.getSalesRefundInfoList()
									.size() - 1 ? order
									.getUserAuthenticateFreightFee()
									: BigDecimal.ZERO);
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_057() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,确认收货,先退一个商品，再退一个商品，订单部分退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);
			OrderDetailPo refundedOrderDetailPo = order.getOrderDetailPoList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			// 发货
			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 第一个申请退款
			RefundService.applyRefundCall(RefundService.buildSingleApplyRefundReq(orderId,
					refundedOrderDetailPo, BigDecimal.ONE, 1));

			// 第二个商品申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleApplyRefundReq(orderId, refundedOrderDetailPo,
							order.getOrderFreight().subtract(BigDecimal.ONE),
							1, "TK" + "1" + orderId);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {
				
				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 商品部分退
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(1);
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo
											.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_058() {
		Logger.start(true, "一个订单包含买手鉴定费商品、买家鉴定费商品、普通商品，第三方+余额支付全款,确认收货,订单全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithThreeTypeProduct();

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 商品全退，加上买家鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum()).add(
							order.getUserAuthenticateFreightFee());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_059() {
		Logger.start(true, "一个订单包含两个买家鉴定费商品，第三方+余额支付全款,确认收货,订单全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {
				
				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 所有买家鉴别费的商品分批退款，最后退买家鉴别费的商品加上买家鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum())
							.add(i != applyRefundReq.getSalesRefundInfoList()
									.size() - 1 ? BigDecimal.ZERO : order
									.getUserAuthenticateFreightFee());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_060() {
		Logger.start(true, "买家承担鉴定费和鉴定运费，第三方+余额支付全款,先申请退全款，然后鉴定中心发货，同意退款失败");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);
			
			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);
			
			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildStandApplyRefundReq(order);
			RefundService.applyRefundCall(applyRefundReq);
			
			// 鉴定中心发货
			TradingCallService.authenticateDelivery(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("false",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				Logger.verifyEquals("ErrOrderAmountNotMatch",
						salesrefundsuccessCall.getString("errorCode"),
						"验证errorCode");
				Logger.verifyEquals("鉴别费已不满足退款条件,请修改退款金额。或商品全部退完才能退鉴别运费！",
						salesrefundsuccessCall.getString("errorMessage"),
						"验证errorMessage");
				
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_AgreeRefund_061() {
		Logger.start(true, "一个订单包含买手鉴定费商品、买家鉴定费商品、普通商品，第三方+余额支付全款,确认收货，买家鉴定费商品全部退款");
		try {
			Logger.comment("前置数据准备");
			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoTypeProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			Long userId = placeOrderResp.getUserId();
			Long sellerId = order.getSellerId();

			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 用余额支付金额
			BigDecimal useAccountAmount = new BigDecimal(47);

			// 支付订单 余额+支付宝组合支付
			// 13 为 app国际支付宝，15 微信
			String payType = "13";

			Long thirdTradingId = TradingCallService.payOrder(
					placeOrderResp.getUserId(), useAccountAmount,
					placeOrderResp.getTradingId(), payType);

			// 支付网关支付回调交易
			PayGateWayCallService.notifyCall(payType,
					String.valueOf(thirdTradingId),
					totalPrice.subtract(useAccountAmount).toString(),
					userId.intValue());

			// 等待支付网关异步处理
			Thread.sleep(5000);

			// 接单
			TradingCallService.sellerAcceptOrder(order.getSellerId(), orderId);
			TradingSyncService.getSyncResult(orderId);

			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			TradingSyncService.getSyncResult(orderId);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			OrderDetailPo buyerAuthenticateOrderDetail = order
					.getOrderDetailPoList()
					.stream()
					.filter(orderDetailPo -> orderDetailPo
							.getAuthenticateFlag() == true)
					.collect(Collectors.toList()).get(0);

			// 申请退款
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleApplyRefundReq(orderId,
							buyerAuthenticateOrderDetail,
							order.getOrderFreight());
			BigDecimal userAuthenticateFeeFreight = order
					.getUserAuthenticateFreightFee();
			applyRefundReq
					.getSalesRefundInfoList()
					.stream()
					.forEach(
							salesRefundInfoVo -> {
								salesRefundInfoVo
										.setRefundAmount(salesRefundInfoVo
												.getRefundAmount()
												.add(userAuthenticateFeeFreight));
							});
			RefundService.applyRefundCall(applyRefundReq);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;
			// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
			RefundFundPo expectRefundFundPo = new RefundFundPo();
			
			BigDecimal tempNoSettlementCouponAmount = BigDecimal.ZERO;

			// 订单表(order)
			OrderPo orderPo = orderShardingWapper
					.selectOrderbyOrderId(orderId);
			BigDecimal accountPaidAmount = orderPo
					.getAccountPaidAmount();
			BigDecimal cardPaidAmount = orderPo.getCardAmount();
			BigDecimal refundedAccountAmount = BigDecimal.ZERO;

			BigDecimal accountAmount = BigDecimal.ZERO;
			BigDecimal thirdpartyAmount = BigDecimal.ZERO;
			BigDecimal cardAmount = BigDecimal.ZERO;
			BigDecimal userAuthenticateFee = BigDecimal.ZERO;

			// 已退款的预付卡金额
			BigDecimal refundedCardAmount = BigDecimal.ZERO;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");

				if (salesrefundsuccessCall.getString("success").equals("true")) {

					Thread.sleep(5000);

					// 支付网关退款回调
					PayGateWayCallService.refundNotifyCall("13",
							thirdTradingId.toString(), userId.intValue());

					Thread.sleep(5000);

					SalesRefundInfoVo refund = applyRefundReq
							.getSalesRefundInfoList().get(i);

					String refundBillNo = refund.getRefundBillNo();

					RefundBillPo actualRefundBillPo = orderShardingWapper
							.selectRefundBillByBillNo(refundBillNo);

					OrderDetailPo orderDetailPo = orderShardingWapper
							.selectOrderDetailbyOrderId(orderId).get(i);

					cardAmount = actualRefundBillPo.getCardAmount();
					BigDecimal refundRebateAmount = RefundService
							.apportionRefundRebate(orderDetailPo,
									refund.getRefundAmount());
					
					// 鉴定商品全退，加上买家鉴定物流费
					userAuthenticateFee = RefundService.getUserAuthenticateFee(
							orderDetailPo, refund.getRefundProductNum()).add(
							order.getUserAuthenticateFreightFee());
					
					// 退款，优先退 预付卡
					if (Utils.isBiggerThanOrEqual(
							cardPaidAmount.subtract(refundedCardAmount),
							refund.getRefundAmount()))
						cardAmount = refund.getRefundAmount();
					else
						cardAmount = cardPaidAmount
								.subtract(refundedCardAmount);

					refundedCardAmount = refundedCardAmount.add(cardAmount);

					// 退款减去 退 预付卡
					BigDecimal refundAmount = refund.getRefundAmount()
							.subtract(cardAmount);

					// 余额支付大于退款金额，先退余额
					if (Utils.isBiggerThanOrEqual(accountPaidAmount
							.subtract(refundedAccountAmount), refundAmount)) {

						accountAmount = refundAmount;
					} else {

						accountAmount = accountPaidAmount
								.subtract(refundedAccountAmount);
						thirdpartyAmount = refundAmount
								.subtract(accountAmount);
					}

					refundedAccountAmount = refundedAccountAmount
							.add(accountAmount);

					RefundBillPo expectedRefundBillPo = new RefundBillPo();

					expectedRefundBillPo.setFreight(RefundService
							.apportionFreight(
									orderDetailPo,
									refund.getRefundAmount().subtract(
											userAuthenticateFee),
									refund.getRefundProductNum()));
					expectedRefundBillPo.setOrderId(orderId);
					expectedRefundBillPo.setSellerId(orderPo.getSellerId());
					expectedRefundBillPo.setUserId(orderPo.getUserId());
					expectedRefundBillPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectedRefundBillPo.setProductCount(orderDetailPo.getProductCount());
					expectedRefundBillPo.setAccountAmount(accountAmount);
					expectedRefundBillPo.setCardAmount(cardAmount);
					expectedRefundBillPo
							.setThirdpartyAmount(thirdpartyAmount);
					expectedRefundBillPo.setRefundBillNo(refundBillNo);
					expectedRefundBillPo
							.setCatalogId(refund.getCatalogId());
					expectedRefundBillPo.setTotalAmount(refund
							.getRefundAmount());
					expectedRefundBillPo.setTopspeedRefund(false);
					expectedRefundBillPo.setAfterReceiving(true);
					expectedRefundBillPo.setRefundStatus(1);
					expectedRefundBillPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectedRefundBillPo
							.setRebateAmount(refundRebateAmount);
					expectedRefundBillPo.setUserAuthenticateFee(userAuthenticateFee);

					BigDecimal noSettlementCouponAmount = BigDecimal.ZERO;

					if (i == applyRefundReq.getSalesRefundInfoList().size() - 1) {

						noSettlementCouponAmount = orderPo
								.getYmtCouponAmount().subtract(
										tempNoSettlementCouponAmount);
					}

					else {
						noSettlementCouponAmount = RefundService
								.devideThenMultiply(
										refund.getRefundAmount(),
										order.getOrderPayableAmount().add(
												orderPo.getCardAmount()),
										Utils.zeroIfNull(orderPo
												.getYmtCouponAmount()));

						tempNoSettlementCouponAmount = tempNoSettlementCouponAmount
								.add(noSettlementCouponAmount);
					}

					expectedRefundBillPo
							.setNoSettlementCouponAmount(noSettlementCouponAmount);

					expectedRefundBillPo.setRefundBillStatus(10);

					RefundService.verifyRefundBillDb(expectedRefundBillPo,
							actualRefundBillPo);

					if (cardAmount.compareTo(BigDecimal.ZERO) == 1)
						continue;

					// 用户退款资金详情表（user_refund_fund_detail）
					UserRefundFundDetailPo userRefundFundDetailPo = orderShardingWapper
							.selectUserRefundFundDetailByBizno(refundBillNo);

					UserRefundFundDetailPo expectUserRefundFundDetailPo = new UserRefundFundDetailPo();

					expectUserRefundFundDetailPo.setPaymentId(Long
							.valueOf(thirdTradingId));

					expectUserRefundFundDetailPo.setBizType(1);

					expectUserRefundFundDetailPo
							.setAccountAmount(accountAmount);

					int accountRefundStatus = -1;

					if (Utils
							.isBiggerThan(expectUserRefundFundDetailPo
									.getAccountAmount(), BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry accountEntry = RefundService
								.getAccountEntry(userId, orderId + "_"
										+ refundBillNo + "_1", refundBillNo);

						DataUtil.verifyDecimalEquals(
								expectUserRefundFundDetailPo
										.getAccountAmount(),
								accountEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setRebateAmount(refundRebateAmount);

					if (Utils.isBiggerThan(
							expectUserRefundFundDetailPo.getRebateAmount(),
							BigDecimal.ZERO)) {

						accountRefundStatus = 4;

						// 退余额校验余额账户退款流水记录
						AccountEntry rebateEntry = RefundService
								.getRefundRebateAmountAccountEntry(
										userId,
										orderId + "_" + refundBillNo + "_1",
										refundBillNo);

						DataUtil.verifyDecimalEquals(
								refundRebateAmount,
								rebateEntry.getAmount(),
								String.format(
										"退款单号 refundBillNo : %s 校验余额退款流水记录 ",
										refundBillNo));
					}

					expectUserRefundFundDetailPo
							.setAccountRefundStatus(accountRefundStatus);

					expectUserRefundFundDetailPo
							.setThirdpartyAmount(refundAmount
									.subtract(accountAmount));

					int thirdpartyRefundStatus = -1;

					if (Utils.isBiggerThan(expectUserRefundFundDetailPo
							.getThirdpartyAmount(), BigDecimal.ZERO)) {
						thirdpartyRefundStatus = 4;

					}

					expectUserRefundFundDetailPo
							.setThirdpartyRefundStatus(thirdpartyRefundStatus);
					expectUserRefundFundDetailPo
							.setThirdpartyDiscount(BigDecimal.ZERO);
					expectUserRefundFundDetailPo.setRetryTimes(0);
					expectUserRefundFundDetailPo.setMemo("0");
					expectUserRefundFundDetailPo.setOrderId(orderId);

					RefundService.verifyUserRefundFundDetailDb(
							expectUserRefundFundDetailPo,
							userRefundFundDetailPo);

					// 验证refund_fund表数据，一个订单只有一条数据，订单每个商品发生退款，表中的金额将会根据退款金额累计
					RefundFundPo actualRefundFundPo = orderShardingWapper
							.selectRefundFundByOrderId(orderId);

					orderShardingWapper.clearCache();

					expectRefundFundPo.setFreight(Utils.zeroIfNull(
							expectRefundFundPo.getFreight()).add(
									expectedRefundBillPo.getFreight()));

					expectRefundFundPo
							.setDeductedCouponAmount(BigDecimal.ZERO);
					expectRefundFundPo.setOrderId(orderId);
					expectRefundFundPo
							.setUserThirdpartyAmount(expectRefundFundPo
									.getUserThirdpartyAmount().add(
											userRefundFundDetailPo
													.getThirdpartyAmount()));
					expectRefundFundPo
							.setThirdpartyDiscount(expectRefundFundPo
									.getThirdpartyDiscount()
									.add(userRefundFundDetailPo
											.getThirdpartyDiscount()));
					expectRefundFundPo
							.setUserAccountAmount(expectRefundFundPo
									.getUserAccountAmount().add(
											userRefundFundDetailPo
													.getAccountAmount()));
					expectRefundFundPo.setDeductedAmount(expectRefundFundPo
							.getDeductedAmount()
							.add(actualRefundBillPo.getTotalAmount())
							.subtract(userAuthenticateFee));
					expectRefundFundPo.setUserRebateAmount(Utils
							.zeroIfNull(
									expectRefundFundPo
											.getUserRebateAmount()).add(
									refundRebateAmount));
					expectRefundFundPo
							.setUserAuthenticateFee(userAuthenticateFee
									.add(expectRefundFundPo.getUserAuthenticateFee()));

					RefundService.verifyRefundFundDb(expectRefundFundPo,
							actualRefundFundPo);
				}
				i++;
			}
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	public static void main(String[] args) throws ClientProtocolException,
			IOException {
		AgreeRefundReq salesrefundsuccessReq = new AgreeRefundReq();
		AgreeRefundCall call = new AgreeRefundCall();

		salesrefundsuccessReq.setOrderId(10174108699L);
		salesrefundsuccessReq.setRefundBillNo("TH010174108699");

		call.setData(salesrefundsuccessReq);
		call.callService();
	}
}
